﻿using System;
using GeoAPI.Geometries;

namespace NetTopologySuite.Precision
{
	public class CommonBitsRemover
	{
		public void Add(IGeometry geom)
		{
			geom.Apply(this._ccFilter);
			this._commonCoord = this._ccFilter.CommonCoordinate;
		}

		public Coordinate CommonCoordinate
		{
			get
			{
				return this._commonCoord;
			}
		}

		public IGeometry RemoveCommonBits(IGeometry geom)
		{
			if (this._commonCoord.X == 0.0 && this._commonCoord.Y == 0.0)
			{
				return geom;
			}
			Coordinate coordinate = new Coordinate(this._commonCoord);
			coordinate.X = -coordinate.X;
			coordinate.Y = -coordinate.Y;
			CommonBitsRemover.Translater filter = new CommonBitsRemover.Translater(coordinate);
			geom.Apply(filter);
			geom.GeometryChanged();
			return geom;
		}

		public void AddCommonBits(IGeometry geom)
		{
			CommonBitsRemover.Translater filter = new CommonBitsRemover.Translater(this._commonCoord);
			geom.Apply(filter);
			geom.GeometryChanged();
		}

		private Coordinate _commonCoord;

		private readonly CommonBitsRemover.CommonCoordinateFilter _ccFilter = new CommonBitsRemover.CommonCoordinateFilter();

		public class CommonCoordinateFilter : ICoordinateFilter
		{
			public void Filter(Coordinate coord)
			{
				this._commonBitsX.Add(coord.X);
				this._commonBitsY.Add(coord.Y);
			}

			public Coordinate CommonCoordinate
			{
				get
				{
					return new Coordinate(this._commonBitsX.Common, this._commonBitsY.Common);
				}
			}

			private readonly CommonBits _commonBitsX = new CommonBits();

			private readonly CommonBits _commonBitsY = new CommonBits();
		}

		private class Translater : ICoordinateSequenceFilter
		{
			public Translater(Coordinate trans)
			{
				this._trans = trans;
			}

			public void Filter(ICoordinateSequence seq, int i)
			{
				double value = seq.GetOrdinate(i, Ordinate.X) + this._trans.X;
				double value2 = seq.GetOrdinate(i, Ordinate.Y) + this._trans.Y;
				seq.SetOrdinate(i, Ordinate.X, value);
				seq.SetOrdinate(i, Ordinate.Y, value2);
			}

			public bool Done
			{
				get
				{
					return false;
				}
			}

			public bool GeometryChanged
			{
				get
				{
					return true;
				}
			}

			private readonly Coordinate _trans;
		}
	}
}
